<template>
  <div class="m-editor-container">
    <div class="coding-tool-bar">
      <el-tooltip placement="bottom" content="恢复默认代码">
        <span class="m-editor-tool-icon" @click="setDefaultCode">
          <el-icon :size="20"><refresh-left/></el-icon>
        </span>
      </el-tooltip>
      <el-tooltip placement="bottom" content="暂存代码到本地">
        <span class="m-editor-tool-icon" @click="saveCodeToLocal">
          <el-icon :size="20"><download/></el-icon>
        </span>
      </el-tooltip>
      <el-tooltip placement="bottom" content="从本地恢复代码">
        <span class="m-editor-tool-icon" @click="loadCodeToLocal">
          <el-icon :size="20"><upload /></el-icon>
        </span>
      </el-tooltip>
      <el-select placeholder="选择编程语言" @change="changeLanguage" class="language-choose" v-model="language" size="medium">
        <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value"
        >
        </el-option>
      </el-select>
      <el-button type="primary" plain @click="submit">提交代码</el-button>
    </div>
    <div id="container" class="m-editor-main"></div>
  </div>
</template>

<script>
import {loader} from "../gloable/loader";
import {RefreshLeft, Download,Upload} from "@element-plus/icons"
import {Problem} from '/src/utils/http/problem'
import {Record} from "../utils/http/record";

import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution';
import 'monaco-editor/esm/vs/basic-languages/go/go.contribution';
import 'monaco-editor/esm/vs/basic-languages/cpp/cpp.contribution';
import 'monaco-editor/esm/vs/basic-languages/java/java.contribution';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';

import {toRaw} from '@vue/reactivity'
import {ElMessageBox} from 'element-plus'

const getStoredLanguage = ()=>{
  let l = localStorage.getItem("sl");
  if (!!l)  {
    return l;
  }
  return 'java'
}

let inst;

export default {
  name: "Editor",
  emits:["submitSuccess"],
  components: {
    RefreshLeft, Download,Upload
  },
  data() {
    return {
      language: getStoredLanguage(),
      preLanguage: 'go',
      editor: null,//文本编辑器,
      options: [
        {
          value: 'java',
          label: 'Java 8',
        },
        {
          value: 'go',
          label: 'Go 1.16',
        },
        {
          value: 'cpp',
          label: 'C++ 11',
        }
      ]
    }
  },
  mounted() {
    this.initEditor();
    loader.stop()
  },
  methods: {
    initEditor() {
      // 初始化编辑器，确保dom已经渲染
      this.editor = monaco.editor.create(document.getElementById('container'), {
        value: this.getDefaultCode(),//编辑器初始显示文字
        language: this.language,//语言支持自行查阅demo
        automaticLayout: true,//自动布局
        theme: 'vs'
      });
    },
    async submit(){
      let data = {
        language:Record.getLanguageId(this.getLanguage()),
        code:this.getValue(),
        pid:parseInt(this.$route.params.proId)
      }
      let resp = await Record.submit(data)
      if (resp.success){
        this.$success("提交成功")
        let recordId = resp.data.id;
        this.$emit("submitSuccess",recordId)
      }else {
        this.$error("提交失败："+resp.message)
      }
    },
    getValue() {
      return toRaw(this.editor).getValue()
    },
    getLanguage() {
      return toRaw(this.language)
    },
    setCode(code){
      toRaw(this.editor).setValue(code)
    },
    changeLanguage(v) {
      ElMessageBox.confirm(
          '修改编程语言将会重置代码，确认切换吗？',
          '注意！',
          {
            confirmButtonText: '好的',
            cancelButtonText: '算了',
            type: 'warning',
          }
      )
          .then(() => {
            this.preLanguage = v
            localStorage.setItem("sl",v)
            monaco.editor.setModelLanguage(toRaw(this.editor).getModel(), v)
            toRaw(this.editor).setValue(this.getDefaultCode())
          })
          .catch(() => {
            this.language = this.preLanguage
          })
    },
    getDefaultCode() {
      return Problem.getDefaultCode(toRaw(this.language), this.$route.params.proId)
    },
    loadCodeToLocal(){
      let id = this.$route.params.proId
      let uid = this.$store.state.userInfo.id
      let code = localStorage.getItem(`code:${id}:${uid}:${this.getLanguage()}`)
      if (!code){
        this.$warning(`您在本题暂未存储过${this.getLanguage()}语言的代码`)
        return
      }
      this.$success('加载成功',1000)
      this.setCode(code)
    },
    saveCodeToLocal(){
      let code = this.getValue();
      let id = this.$route.params.proId
      let uid = this.$store.state.userInfo.id
      localStorage.setItem(`code:${id}:${uid}:${this.getLanguage()}`,code)
      this.$success('保存成功',1000)
    },
    setDefaultCode(){
      this.setCode(this.getDefaultCode())
      this.$success('加载成功',1000)
    }
  },
  watch: {
    $route(to, from) {
      toRaw(this.editor).setValue(this.getDefaultCode())
      loader.stop()
    }
  }
}
</script>

<style scoped>
.m-editor-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  position: relative;
}

.m-editor-main {
  margin-top: 46px;
  margin-bottom: auto;
  height: 100%;
  max-height: 100%;
  text-align: left;
}

.coding-tool-bar {
  display: flex;
  justify-content: space-around;
  background: #fafafa;
  user-select: none;
  position: absolute;
  width: 100%;
  height: 45px;
  align-items: center;
  padding-left: 60px;
  box-sizing: border-box;
}

.coding-tool {
  cursor: pointer;
  user-select: none;
}

.language-choose {
  width: 130px;
  border: 1px solid #b3d8ff;
  box-shadow: 0 1px 4px rgba(0,0,0,0.3);
  border-radius: 5px;
}

.m-editor-tool-icon{
  cursor: pointer;
  height: 25px;
  width: 25px;
  border-radius: 12.5px;
  border: 1px solid #b3d8ff;
  box-shadow: 0 1px 4px rgba(0,0,0,0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #409eff;
}

.m-editor-language-select{

}
</style>